package utils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.util.ArrayList;
import java.util.List;

public class HtmlTableToArray {

    public static List<List<List<String>>> parse(String html) {
        List<List<List<String>>> ret = new ArrayList<>();
        Document document = Jsoup.parse(html);
        for (Element table : document.select("table")) {
            ret.add(parseTable(table));
        }
        return ret;
    }

    private static List<List<String>> parseTable(Element tableEle) {
        Table table = new Table();
        for (Element tr : tableEle.select("tr")) {
            table.movetoNextRow();
            for (Element cell : tr.children()) {
                String tagname = cell.tagName();
                if ("td".equalsIgnoreCase(tagname) || "th".equalsIgnoreCase(tagname)) {
                    int rowspan = rowspan(cell);
                    int colspan = colspan(cell);
                    table.addCellContent(rowspan, colspan, cell.text());
                }
            }
        }
        return table.getContent();
    }

    private static int colspan(Element cell) {
        String rowspan = cell.attr("colspan");
        if (isEmpty(rowspan)) {
            return 1;
        } else {
            return Integer.parseInt(rowspan);
        }
    }

    private static int rowspan(Element cell) {
        String rowspan = cell.attr("rowspan");
        if (isEmpty(rowspan)) {
            return 1;
        } else {
            return Integer.parseInt(rowspan);
        }
    }

    private static boolean isEmpty(String rowspan) {
        return rowspan == null || rowspan.isEmpty();
    }

    static class Table {

        private int row = -1;
        private int col = -1;
        private List<List<String>> content = new ArrayList<>();

        public List<List<String>> getContent() {
            return content;
        }

        public void addCellContent(int rowspan, int colspan, String text) {

            int nextCol = nextCol();

            for (int r = row; r < row + rowspan; r++) {
                for (int c = nextCol; c < nextCol + colspan; c++) {
                    updateCellContent(r, c, text);
                }
            }

            this.col = nextCol + colspan;

        }

        private void updateCellContent(int r, int c, String text) {
            List<String> rowarray = getRow(r);
            while (c >= rowarray.size()) {
                rowarray.add(null);
            }
            rowarray.set(c, text);
        }

        private int nextCol() {
            List<String> rowarray = getRow(row);

            int netCol = col;
            while (netCol < rowarray.size() && rowarray.get(netCol) != null) {
                netCol++;
            }

            return netCol;
        }

        private List<String> getRow(int row) {
            if (row > content.size() - 1) {
                content.add(new ArrayList<>());
            }
            return content.get(row);
        }

        public void movetoNextRow() {
            this.row++;
            this.col = 0;
        }
    }

}
